YUI.add('ajax-uploader', function (Y) {
    /* Any frequently used shortcuts, strings and constants */
    var Lang = Y.Lang,
    Widget = Y.Widget,
    Node = Y.Node,
//    lastStartFuid,
    fuIoTransIdFuidHash = {};

    /* AjaxUploader class constructor */
    function AjaxUploader(config) {
        AjaxUploader.superclass.constructor.apply(this, arguments);
    }

    /* 
     * Required NAME static field, to identify the class and 
     * used as an event prefix, to generate class names etc. (set to the 
     * class name in camel case). 
     */
    AjaxUploader.NAME = "AjaxUploader";
    
    AjaxUploader.UPLOADER_URL = "/fileUploadHandler/?";

    //http://www.m3958.com/smartcfud?&_modelName=com.m3958.firstgwt.server.model.Asset&_relationPropertyName=assets&_relationModelName=com.m3958.firstgwt.server.model.AssetFolder&_subOperationType=MANY_TO_MANY&_relationModelId=36389&_isMaster=false&siteId=8566&_tz=Asia%2FShanghai&_operationType=fetch&_startRow=0&_endRow=75&_sortBy=-createdAt&_textMatchStyle=substring&_componentId=isc_ListGrid_1&_dataSource=assetDS&isc_metaDataPrefix=_&isc_dataFormat=json
    //http://www.m3958.com/fileUploadHandler/?siteId=8566&WANTED_RESPONSE=JSON&submitId=e6c4415ec81d4c0c90baffab18bf7b850

	/*
	 * The attribute configuration for the AjaxUploader widget. Attributes can be
	 * defined with default values, get/set functions and validator functions
	 * as with any other class extending Base.
	 */
	AjaxUploader.ATTRS = {
	    // The minimum value for the AjaxUploader.
	    siteId : {
	        value:-1
	    },
	    tmp : {
	    	setter : function(val){
	    		if(val){
	    			return true;
	    		}else{
	    			return false;
	    		}
	    	}
	    },
	    // override default ("null"), required for focus()
	    tabIndex: {
	        value: 0
	    },
	
	    // The strings for the AjaxUploader UI. This attribute is 
	    // defined by the base Widget class but has an empty value. The
	    // AjaxUploader is simply providing a default value for the attribute.
	    strings: {
	        value: {
	            tooltip: "Press the arrow up/down keys for minor increments, page up/down for major increments.",
	            sure: "sure",
	            cancel: "cancel"
	        }
	    }
	};
	
	/* Static constant used to identify the classname applied to the AjaxUploaders value field */
	AjaxUploader.FILE_CLASS = Y.ClassNameManager.getClassName(AjaxUploader.NAME, "file");
	AjaxUploader.FORM_CLASS = Y.ClassNameManager.getClassName(AjaxUploader.NAME, "form");
	
	/* Static constants used to define the markup templates used to create AjaxUploader DOM elements */
	AjaxUploader.FILE_TEMPLATE = '<input name="file" type="file" class="' + AjaxUploader.FILE_CLASS + '">';
	AjaxUploader.BTN_TEMPLATE = '<button type="button"></button>';
	
	AjaxUploader.FORM_TEMPLATE = '<form action="/fileUploadHandler/?" enctype="multipart/form-data" class="'+ AjaxUploader.FORM_CLASS +'"></form>';
	
	/* 
	 * The HTML_PARSER static constant is used by the Widget base class to populate 
	 * the configuration for the AjaxUploader instance from markup already on the page.
	 *
	 * The AjaxUploader class attempts to set the value of the AjaxUploader widget if it
	 * finds the appropriate input element on the page.
	 */
	AjaxUploader.HTML_PARSER = {
//	    file: function (srcNode) {
//	        return srcNode.one('.' + AjaxUploader.FILE_CLASS); 
//	    }
	};
	
	/* AjaxUploader extends the base Widget class */
	Y.extend(AjaxUploader, Widget, {
	
	    /*
	     * initializer is part of the lifecycle introduced by 
	     * the Widget class. It is invoked during construction,
	     * and can be used to setup instance specific state.
	     * 
	     * The AjaxUploader class does not need to perform anything
	     * specific in this method, but it is left in as an example.
	     */
	    initializer: function() {
	        // Not doing anything special during initialization
	    	this.fuid = Y.guid('fileupload_');
	    },
	
	    /*
	     * destructor is part of the lifecycle introduced by 
	     * the Widget class. It is invoked during destruction,
	     * and can be used to cleanup instance specific state.
	     * 
	     * The AjaxUploader cleans up any node references it's holding
	     * onto. The Widget classes destructor will purge the 
	     * widget's bounding box of event listeners, so AjaxUploader 
	     * only needs to clean up listeners it attaches outside of 
	     * the bounding box.
	     */
	    destructor : function() {
	    	this._myCleanUp();
	    },
	    
	    _myCleanUp : function(){
//	        this._onIoStart.detach();
	        this._onIoComplete.detach();
	        this.formNode = null;
	        this.sureBt = null;
	        this.cancelBt = null;
	        this.fileField = null;
	        if(this.timer){
	        	this.timer.cancel();
	        	this.timer = null;
	        }
	        if(fuIoTransIdFuidHash[this.fuid]){
	        	delete fuIoTransIdFuidHash[this.fuid];
	        }
	    },
	
	    /*
	     * renderUI is part of the lifecycle introduced by the
	     * Widget class. Widget's renderer method invokes:
	     *
	     *     renderUI()
	     *     bindUI()
	     *     syncUI()
	     *
	     * renderUI is intended to be used by the Widget subclass
	     * to create or insert new elements into the DOM. 
	     *
	     * For AjaxUploader the method adds the input (if it's not already 
	     * present in the markup), and creates the inc/dec buttons
	     */
	    renderUI : function() {
	    	this._renderForm();
	        this._renderFile();
	        this.pr = new Y.M3958.ProgressBar({visible:false});
	        var cb = this.get('contentBox');
	        this.pr.render(cb);
	        this.msgBox = Node.create('<span style="display:none;"></span>');
	        cb.appendChild(this.msgBox);
	    },
	
	    /*
	     * bindUI is intended to be used by the Widget subclass 
	     * to bind any event listeners which will drive the Widget UI.
	     * 
	     * It will generally bind event listeners for attribute change
	     * events, to update the state of the rendered UI in response 
	     * to attribute value changes, and also attach any DOM events,
	     * to activate the UI.
	     * 
	     * For AjaxUploader, the method:
	     *
	     * - Sets up the attribute change listener for the "value" attribute
	     *
	     * - Binds key listeners for the arrow/page keys
	     * - Binds mouseup/down listeners on the boundingBox, document respectively.
	     * - Binds a simple change listener on the input box.
	     */
	    bindUI : function() {
	    	var formNode = this.formNode;
	        var cfg = {
	                method: 'POST',
	                form: {
	                    id: formNode,
	                    upload: true
	                }
	            };
	            
	            var fuid = this.fuid;
	            
	            this._onIoComplete = Y.on('io:complete', this._uploadComplete, this, {});
	            
	            var outThis = this;
	            var progressCfg = {
	                    on: {
//	                        start: tH.start,
//	                        complete: tH.complete,
	                        success: outThis._progressSuccess
//	                        failure: tH.failure,
//	                        end: tH.end
	                    },
	                    context: outThis,
	                    arguments: {
//		                               start: 'foo',
//		                               complete: 'bar',
//		                               success: 'baz',
//		                               failure: 'Oh no!',
//		                               end: 'boo'
	                               }
	                };
	            
	            this.fileField.after('valueChange',function(e){
	            	if(!this.fileField.get('value')){
	            		alert('请选择文件！');
	            		return;
	            	}
//	            	lastStartFuid = this.fuid;
	            	var uri = AjaxUploader.UPLOADER_URL + "siteId=" + this.get('siteId') + '&WANTED_RESPONSE=JSON&submitId=' + fuid + '&tmp=' + this.get('tmp');
	            	var request = Y.io(uri, cfg);
	            	fuIoTransIdFuidHash[fuid] =  request.id;
	            	this._uploadStart();
	            	this.timer = Y.later(1500,this,function(e){
	            		var prequest = Y.io('/uploadprogress/?submitId=' + outThis.fuid, progressCfg);
	            	},[],true);
	            },this);
//	        this.after("valueChange", this._afterValueChange);
//	
//	        var boundingBox = this.get("boundingBox");
//	
//	        // Looking for a key event which will fire continuously across browsers while the key is held down. 38, 40 = arrow up/down, 33, 34 = page up/down
//	        var keyEventSpec = (!Y.UA.opera) ? "down:" : "press:";
//	        keyEventSpec += "38, 40, 33, 34";
//	
//	        Y.on("key", Y.bind(this._onDirectionKey, this), boundingBox, keyEventSpec);
//	        Y.on("mousedown", Y.bind(this._onMouseDown, this), boundingBox);
//	
//	        this._documentMouseUpHandle = Y.on("mouseup", Y.bind(this._onDocMouseUp, this), boundingBox.get("ownerDocument"));
//	
//	        Y.on("change", Y.bind(this._onInputChange, this), this.inputNode);
	    },
	
	    /*
	     * syncUI is intended to be used by the Widget subclass to
	     * update the UI to reflect the current state of the widget.
	     * 
	     * For AjaxUploader, the method sets the value of the input field,
	     * to match the current state of the value attribute.
	     */
	    syncUI : function() {
//	        this._uiSetValue(this.get("value"));
	    },
	    
	    _progressSuccess : function(id, o, args){
	    	var data = Y.JSON.parse(o.responseText);
	    	this.pr.set('progress',data.readedBytes/data.totalBytes);
//	    	currentIndex: 0
//	    	fileNames: []
//	    	readedBytes: 3396
//	    	totalBytes: 3396
	    },
	    
	    _uploadStart : function(){
	    	var cb = this.get('contentBox');
	    	var f = cb.one('.' + AjaxUploader.FORM_CLASS);
	    	var fi = cb.one('.' + AjaxUploader.FILE_CLASS);
	    	this.msgBox.setContent(fi.get('value'));
	    	this.msgBox.show();
	    	f.hide();
	    	this.pr.show();
	    },
	    
	    _uploadComplete : function(id, o, args){
	    	var curId = fuIoTransIdFuidHash[this.fuid];
	    	if(curId != id)return;
            var data = o.responseText; // Response data.
            var res = Y.JSON.parse(data);
            var id = id; // Transaction ID.
	    	var cb = this.get('contentBox');
	    	var fi = cb.one('.' + AjaxUploader.FILE_CLASS);
            if(res.STATUS === 0 && res.DATA && res.DATA.length === 1){
            	var tpl = '<a href="{url}" target="_blank">{originName}</a>';
            	this.msgBox.setContent(Lang.sub(tpl,res.DATA[0]));
            }else{
            	this.msgBox.setContent(res.DATA[0].originName + ",上传失败！");
            }
            this.pr.hide();
            this.timer.cancel();
            this.timer = null;
            this._myCleanUp();
	    },
	    
	    _renderForm : function(){
	    	var contentBox = this.get("contentBox"),formNode;
	    	formNode = Node.create(AjaxUploader.FORM_TEMPLATE);
	    	contentBox.appendChild(formNode);
	    	this.formNode = formNode;
	    },
	
	    /*
	     * Creates the input control for the AjaxUploader and adds it to
	     * the widget's content box, if not already in the markup.
	     */
	    _renderFile : function() {
	        var strings = this.get("strings");
	
            var file = Node.create(AjaxUploader.FILE_TEMPLATE);
            this.formNode.appendChild(file);
	
	        file.set("title", strings.tooltip);
	        this.fileField = file;
	    }
	});
    Y.namespace("M3958").AjaxUploader = AjaxUploader;

},'0.0.1',{requires:['widget','io-base','io-upload-iframe','json','event']});